{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {
    "isInteractiveWindowMessageCell": true
   },
   "source": [
    "Connected to pinns_opf (Python 3.9.17)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 1/100 - Cost: 8.1953\n",
      "Epoch 2/100 - Cost: 3.6076\n",
      "Epoch 3/100 - Cost: 2.9557\n",
      "Epoch 4/100 - Cost: 1.4303\n",
      "Epoch 5/100 - Cost: 0.7568\n",
      "Epoch 6/100 - Cost: 0.7073\n",
      "Epoch 7/100 - Cost: 0.2543\n",
      "Epoch 8/100 - Cost: 0.2860\n",
      "Epoch 9/100 - Cost: 0.2731\n",
      "Epoch 10/100 - Cost: 0.3890\n",
      "Epoch 11/100 - Cost: 0.2743\n",
      "Epoch 12/100 - Cost: 0.2774\n",
      "Epoch 13/100 - Cost: 0.2693\n",
      "Epoch 14/100 - Cost: 0.2542\n",
      "Epoch 15/100 - Cost: 0.2208\n",
      "Epoch 16/100 - Cost: 0.2080\n",
      "Epoch 17/100 - Cost: 0.2109\n",
      "Epoch 18/100 - Cost: 0.1882\n",
      "Epoch 19/100 - Cost: 0.2068\n",
      "Epoch 20/100 - Cost: 0.1958\n",
      "Epoch 21/100 - Cost: 0.1694\n",
      "Epoch 22/100 - Cost: 0.1655\n",
      "Epoch 23/100 - Cost: 0.1691\n",
      "Epoch 24/100 - Cost: 0.1578\n",
      "Epoch 25/100 - Cost: 0.1565\n",
      "Epoch 26/100 - Cost: 0.1707\n",
      "Epoch 27/100 - Cost: 0.1738\n",
      "Epoch 28/100 - Cost: 0.1498\n",
      "Epoch 29/100 - Cost: 0.1386\n",
      "Epoch 30/100 - Cost: 0.1336\n",
      "Epoch 31/100 - Cost: 0.1281\n",
      "Epoch 32/100 - Cost: 0.1226\n",
      "Epoch 33/100 - Cost: 0.1179\n",
      "Epoch 34/100 - Cost: 0.1155\n",
      "Epoch 35/100 - Cost: 0.1125\n",
      "Epoch 36/100 - Cost: 0.1055\n",
      "Epoch 37/100 - Cost: 0.1022\n",
      "Epoch 38/100 - Cost: 0.0995\n",
      "Epoch 39/100 - Cost: 0.0974\n",
      "Epoch 40/100 - Cost: 0.0957\n",
      "Epoch 41/100 - Cost: 0.0941\n",
      "Epoch 42/100 - Cost: 0.0927\n",
      "Epoch 43/100 - Cost: 0.0933\n",
      "Epoch 44/100 - Cost: 0.0917\n",
      "Epoch 45/100 - Cost: 0.0905\n",
      "Epoch 46/100 - Cost: 0.0899\n",
      "Epoch 47/100 - Cost: 0.0891\n",
      "Epoch 48/100 - Cost: 0.0883\n",
      "Epoch 49/100 - Cost: 0.0872\n",
      "Epoch 50/100 - Cost: 0.0860\n",
      "Epoch 51/100 - Cost: 0.0848\n",
      "Epoch 52/100 - Cost: 0.0851\n",
      "Epoch 53/100 - Cost: 0.0823\n",
      "Epoch 54/100 - Cost: 0.0812\n",
      "Epoch 55/100 - Cost: 0.0803\n",
      "Epoch 56/100 - Cost: 0.0794\n",
      "Epoch 57/100 - Cost: 0.0789\n",
      "Epoch 58/100 - Cost: 0.0783\n",
      "Epoch 59/100 - Cost: 0.0775\n",
      "Epoch 60/100 - Cost: 0.0767\n",
      "Epoch 61/100 - Cost: 0.0766\n",
      "Epoch 62/100 - Cost: 0.0760\n",
      "Epoch 63/100 - Cost: 0.0755\n",
      "Epoch 64/100 - Cost: 0.0753\n",
      "Epoch 65/100 - Cost: 0.0748\n",
      "Epoch 66/100 - Cost: 0.0742\n",
      "Epoch 67/100 - Cost: 0.0733\n",
      "Epoch 68/100 - Cost: 0.0727\n",
      "Epoch 69/100 - Cost: 0.0724\n",
      "Epoch 70/100 - Cost: 0.0717\n",
      "Epoch 71/100 - Cost: 0.0711\n",
      "Epoch 72/100 - Cost: 0.0707\n",
      "Epoch 73/100 - Cost: 0.0703\n",
      "Epoch 74/100 - Cost: 0.0698\n",
      "Epoch 75/100 - Cost: 0.0693\n",
      "Epoch 76/100 - Cost: 0.0688\n",
      "Epoch 77/100 - Cost: 0.0683\n",
      "Epoch 78/100 - Cost: 0.0678\n",
      "Epoch 79/100 - Cost: 0.0673\n",
      "Epoch 80/100 - Cost: 0.0671\n",
      "Epoch 81/100 - Cost: 0.0663\n",
      "Epoch 82/100 - Cost: 0.0658\n",
      "Epoch 83/100 - Cost: 0.0654\n",
      "Epoch 84/100 - Cost: 0.0650\n",
      "Epoch 85/100 - Cost: 0.0645\n",
      "Epoch 86/100 - Cost: 0.0640\n",
      "Epoch 87/100 - Cost: 0.0634\n",
      "Epoch 88/100 - Cost: 0.0628\n",
      "Epoch 89/100 - Cost: 0.0622\n",
      "Epoch 90/100 - Cost: 0.0617\n",
      "Epoch 91/100 - Cost: 0.0611\n",
      "Epoch 92/100 - Cost: 0.0605\n",
      "Epoch 93/100 - Cost: 0.0600\n",
      "Epoch 94/100 - Cost: 0.0596\n",
      "Epoch 95/100 - Cost: 0.0590\n",
      "Epoch 96/100 - Cost: 0.0586\n",
      "Epoch 97/100 - Cost: 0.0581\n",
      "Epoch 98/100 - Cost: 0.0576\n",
      "Epoch 99/100 - Cost: 0.0572\n",
      "Epoch 100/100 - Cost: 0.0567\n",
      "Training completed in 14700.18 seconds.\n"
     ]
    },
    {
     "data": {
      "image/png": "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o0c1ZMgQpaSkKD4+XjfccIN2795tUcV1x/jx42Wz2TR8+HDvMXodONu3b9ett96qlJQUxcTEqH379lq+fLn368YYPfXUU8rIyFBMTIy6d++uDRs2WFhx7eR2u/Xkk08qOztbMTExatasmcaMGePzrBh67b8vv/xS/fr1U6NGjWSz2fTBBx/4fL0qvd2/f78GDBigxMREJScn684779ShQ4dqXpyBj5kzZ5qoqCjzxhtvmB9++MH88Y9/NMnJyWb37t1Wl1ar9erVy0ydOtWsXbvWrF692vTp08c0adLEHDp0yHvOvffeazIzM838+fPN8uXLzYUXXmguuugiC6uu/ZYuXWqysrLM2WefbR588EHvcXodGPv37zdNmzY1d9xxh1myZIn59ddfzdy5c80vv/ziPWf8+PEmKSnJfPDBB2bNmjXmmmuuMdnZ2ebIkSMWVl77jB071qSkpJiPP/7YbNq0ybz33nsmPj7ePP/8895z6LX/PvnkE/OXv/zFzJo1y0gy77//vs/Xq9Lb3r17m3POOccsXrzYfPXVV+ass84yt9xyS41rI6iconPnzmbIkCHe12632zRq1MiMGzfOwqrqnj179hhJZuHChcYYYw4ePGgcDod57733vOf89NNPRpL59ttvrSqzVsvPzzfNmzc3OTk55rLLLvMGFXodOH/+85/NxRdfXO7XPR6PSU9PN88++6z32MGDB43T6TTvvPNOKEqsM66++mozePBgn2O/+93vzIABA4wx9DqQTg0qVentjz/+aCSZZcuWec+ZM2eOsdlsZvv27TWqh6mfkxQVFWnFihXq3r2791hERIS6d++ub7/91sLK6p7c3FxJUv369SVJK1askMvl8ul9q1at1KRJE3rvpyFDhujqq6/26alErwPpww8/VMeOHfWHP/xBaWlpOu+88/T66697v75p0ybt2rXLp9dJSUm64IIL6HU1XXTRRZo/f77Wr18vSVqzZo0WLVqkq666ShK9Dqaq9Pbbb79VcnKyOnbs6D2ne/fuioiI0JIlS2r0+bX6oYSBtm/fPrndbjVs2NDneMOGDbVu3TqLqqp7PB6Phg8frq5du6pdu3aSpF27dikqKkrJyck+5zZs2FC7du2yoMrabebMmVq5cqWWLVtW6mv0OnB+/fVXTZkyRSNGjNATTzyhZcuWadiwYYqKitLAgQO9/Szr3xR6XT2PPfaY8vLy1KpVK9ntdrndbo0dO1YDBgyQJHodRFXp7a5du5SWlubz9cjISNWvX7/G/SeoIOSGDBmitWvXatGiRVaXUidt27ZNDz74oHJychQdHW11OXWax+NRx44d9cwzz0iSzjvvPK1du1avvPKKBg4caHF1dcu//vUvTZ8+XTNmzFDbtm21evVqDR8+XI0aNaLXdRxTPydp0KCB7HZ7qd0Pu3fvVnp6ukVV1S1Dhw7Vxx9/rAULFqhx48be4+np6SoqKtLBgwd9zqf31bdixQrt2bNH559/viIjIxUZGamFCxfqhRdeUGRkpBo2bEivAyQjI0Nt2rTxOda6dWtt3bpVkrz95N+UmnvkkUf02GOP6eabb1b79u1122236aGHHtK4ceMk0etgqkpv09PTtWfPHp+vFxcXa//+/TXuP0HlJFFRUerQoYPmz5/vPebxeDR//nx16dLFwspqP2OMhg4dqvfff1+ff/65srOzfb7eoUMHORwOn97//PPP2rp1K72vpiuvvFLff/+9Vq9e7f3VsWNHDRgwwPt7eh0YXbt2LbXNfv369WratKkkKTs7W+np6T69zsvL05IlS+h1NRUUFCgiwvdHlt1ul8fjkUSvg6kqve3SpYsOHjyoFStWeM/5/PPP5fF4dMEFF9SsgBotxa2DZs6caZxOp5k2bZr58ccfzd13322Sk5PNrl27rC6tVrvvvvtMUlKS+eKLL8zOnTu9vwoKCrzn3HvvvaZJkybm888/N8uXLzddunQxXbp0sbDquuPkXT/G0OtAWbp0qYmMjDRjx441GzZsMNOnTzexsbHm7bff9p4zfvx4k5ycbGbPnm2+++47c+2117Jl1g8DBw40Z5xxhnd78qxZs0yDBg3Mo48+6j2HXvsvPz/frFq1yqxatcpIMhMnTjSrVq0yW7ZsMcZUrbe9e/c25513nlmyZIlZtGiRad68OduTg2Xy5MmmSZMmJioqynTu3NksXrzY6pJqPUll/po6dar3nCNHjpj777/f1KtXz8TGxprrr7/e7Ny507qi65BTgwq9DpyPPvrItGvXzjidTtOqVSvz2muv+Xzd4/GYJ5980jRs2NA4nU5z5ZVXmp9//tmiamuvvLw88+CDD5omTZqY6Ohoc+aZZ5q//OUvprCw0HsOvfbfggULyvw3euDAgcaYqvX2t99+M7fccouJj483iYmJZtCgQSY/P7/GtdmMOem2fgAAAGGENSoAACBsEVQAAEDYIqgAAICwRVABAABhi6ACAADCFkEFAACELYIKAAAIWwQVAHXSqFGjdO6551pdBoAaIqgAp7k77rhDNptNNptNDodDDRs2VI8ePfTGG294n6NSVdOmTVNycnJA6urWrZu3rujoaLVp00Yvv/xyld//8MMP+zybpCqysrI0adKkalYKIJgIKgDUu3dv7dy5U5s3b9acOXN0+eWX68EHH1Tfvn1VXFxsWV1//OMftXPnTv3444+68cYbNWTIEL3zzjtVem98fLxSUlKCXCGAYCOoAJDT6VR6errOOOMMnX/++XriiSc0e/ZszZkzR9OmTfOeN3HiRLVv315xcXHKzMzU/fffr0OHDkmSvvjiCw0aNEi5ubnekZBRo0ZJkv75z3+qY8eOSkhIUHp6uvr371/qkfBliY2NVXp6us4880yNGjVKzZs314cffihJ2rp1q6699lrFx8crMTFRN954o89j6E+d+rnjjjt03XXX6bnnnlNGRoZSUlI0ZMgQuVwuScdGcLZs2aKHHnrIW78kbdmyRf369VO9evUUFxentm3b6pNPPqlJuwFUA0EFQJmuuOIKnXPOOZo1a5b3WEREhF544QX98MMPevPNN/X555/r0UcflSRddNFFmjRpkhITE7Vz507t3LlTDz/8sCTJ5XJpzJgxWrNmjT744ANt3rxZd9xxR7VriomJUVFRkTwej6699lrt379fCxcuVE5Ojn799VfddNNNFb5/wYIF2rhxoxYsWKA333xT06ZN8waxWbNmqXHjxvrrX//qrV+ShgwZosLCQn355Zf6/vvvNWHCBMXHx1e7dgD+ibS6AADhq1WrVvruu++8r4cPH+79fVZWlp5++mnde++9evnllxUVFaWkpCTZbDalp6f7XGfw4MHe35955pl64YUX1KlTJx06dKhKP/Tdbrfeeecdfffdd7r77rs1f/58ff/999q0aZMyMzMlSW+99Zbatm2rZcuWqVOnTmVep169enrxxRdlt9vVqlUrXX311Zo/f77++Mc/qn79+rLb7d5RnxJbt27VDTfcoPbt23vrBxA6jKgAKJcxxjsFIknz5s3TlVdeqTPOOEMJCQm67bbb9Ntvv6mgoKDC66xYsUL9+vVTkyZNlJCQoMsuu0zSsRBQkZdfflnx8fGKiYnRH//4Rz300EO677779NNPPykzM9MbUiSpTZs2Sk5O1k8//VTu9dq2bSu73e59nZGRUekU1LBhw/T000+ra9euGjlypE9wAxB8BBUA5frpp5+UnZ0tSdq8ebP69u2rs88+W//5z3+0YsUKvfTSS5KkoqKicq9x+PBh9erVS4mJiZo+fbqWLVum999/v9L3SdKAAQO0evVqbdq0SYcPH9bEiRMVEeH/P1sOh8Pntc1mq3Rn01133aVff/1Vt912m77//nt17NhRkydP9rsGANVDUAFQps8//1zff/+9brjhBknHRkU8Ho/+/ve/68ILL1SLFi20Y8cOn/dERUXJ7Xb7HFu3bp1+++03jR8/XpdccolatWpVpYW0kpSUlKSzzjpLZ5xxhk9Aad26tbZt26Zt27Z5j/344486ePCg2rRp4+8fucz6JSkzM1P33nuvZs2apT/96U96/fXX/f4MANVDUAGgwsJC7dq1S9u3b9fKlSv1zDPP6Nprr1Xfvn11++23S5LOOussuVwuTZ48Wb/++qv++c9/6pVXXvG5TlZWlg4dOqT58+dr3759KigoUJMmTRQVFeV934cffqgxY8bUqN7u3burffv2GjBggFauXKmlS5fq9ttv12WXXaaOHTv6fd2srCx9+eWX2r59u/bt2yfp2LqcuXPnatOmTVq5cqUWLFig1q1b16h+AFVHUAGgTz/9VBkZGcrKylLv3r21YMECvfDCC5o9e7Z3Tcc555yjiRMnasKECWrXrp2mT5+ucePG+Vznoosu0r333qubbrpJqamp+tvf/qbU1FRNmzZN7733ntq0aaPx48frueeeq1G9NptNs2fPVr169XTppZeqe/fuOvPMM/Xuu+/W6Lp//etftXnzZjVr1kypqamSji3kHTJkiFq3bq3evXurRYsW1brxHICasRljjNVFAAAAlIURFQAAELYIKgAAIGwRVAAAQNgiqAAAgLBFUAEAAGGLoAIAAMIWQQUAAIQtggoAAAhbBBUAABC2CCoAACBsEVQAAEDYIqgAAICw9f/XQZcq5dTLhQAAAABJRU5ErkJggg==",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "import os\n",
    "os.chdir(os.path.dirname(os.path.abspath(__file__)))\n",
    "import sys\n",
    "import pickle\n",
    "import logging\n",
    "import time\n",
    "import torch\n",
    "import torch.nn.functional as F\n",
    "from torch_geometric_temporal.signal import StaticGraphTemporalSignal\n",
    "from torch_geometric_temporal.signal import temporal_signal_split\n",
    "import matplotlib.pyplot as plt\n",
    "from model import RecurrentGCN\n",
    "from utilities import pinns_loss \n",
    "def train_model(lr, batch_size, epochs, pinns_loss, _lambda):\n",
    "    start_time = time.time()\n",
    "    # Create and configure logger\n",
    "    logging.basicConfig(filename=\"std.log\", format='%(asctime)s %(message)s', filemode='w')\n",
    "    # Create an object\n",
    "    logger = logging.getLogger()\n",
    "    # Set log level to DEBUG\n",
    "    logger.setLevel(logging.DEBUG)\n",
    "    handler = logging.StreamHandler(sys.stdout)\n",
    "    handler.setLevel(logging.DEBUG)\n",
    "    # GPU support\n",
    "    DEVICE = torch.device('cpu')  # Change to cuda if available\n",
    "    shuffle = True\n",
    "    # Change the current working directory to the script's directory\n",
    "    os.chdir(os.path.dirname(os.path.abspath(__file__)))\n",
    "    # Load the data from the pickle file\n",
    "    with open('../../data/processed/data_converged_noise.pickle', 'rb') as file:\n",
    "        loaded_data = pickle.load(file)\n",
    "    # Access the loaded data\n",
    "    edge_index = loaded_data['edge_index']\n",
    "    edge_weight = loaded_data['edge_weight']\n",
    "    features_seq = loaded_data['features_seq']\n",
    "    targets_seq = loaded_data['targets_seq']\n",
    "    dataset = StaticGraphTemporalSignal(\n",
    "        edge_index=edge_index, edge_weight=edge_weight,\n",
    "        features=features_seq, targets=targets_seq\n",
    "    )\n",
    "    train_dataset, test_dataset = temporal_signal_split(dataset, train_ratio=0.8)\n",
    "    model = RecurrentGCN(node_features=9)\n",
    "    optimizer = torch.optim.Adam(model.parameters(), lr=lr)\n",
    "    n = 5  # number of nodes\n",
    "    v_lower = torch.ones((n, 1))*0.93\n",
    "    v_upper = torch.ones((n, 1))*1.07\n",
    "    costs, model_path = model._train(model, train_dataset=train_dataset, epochs=epochs, lr=lr, h=None, c=None, pinns_loss=pinns_loss,  _lambda=_lambda, v_lower=v_lower, v_upper=v_upper)\n",
    "    print(f\"Training completed in {time.time() - start_time:.2f} seconds.\")\n",
    "    return costs, model_path\n",
    "\n",
    "if __name__ == \"__main__\":\n",
    "    learning_rate = 0.05\n",
    "    batch_size = 32\n",
    "    num_epochs = 100\n",
    "    _lambda = 0.3\n",
    "    costs, model_path = train_model(lr=learning_rate, batch_size=batch_size, epochs=num_epochs, pinns_loss=pinns_loss, _lambda=_lambda)\n",
    "    # Plot the predictions\n",
    "    plt.plot(range(len(costs)), costs, marker='o', linestyle='-')\n",
    "    plt.xlabel('Data Points')\n",
    "    plt.ylabel('Predictions')\n",
    "    plt.title('Predictions Plot')\n",
    "    plt.grid(True)\n",
    "    plt.show()\n",
    "    with open('costs_pinns_100.pkl', 'wb') as f:\n",
    "        pickle.dump(costs, f)"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "pinns_opf",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "name": "python",
   "version": "3.9.17"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
